/* eslint-disable prefer-const */
import {
  defineComponent,
  h,
  PropType,
  reactive,
  renderSlot,
  resolveComponent,
  VNode,
} from 'vue';
import { useController, useNamespace } from '@ibiz-template/vue3-util';
import { IDEFormDetail, IDEFormItem } from '@ibiz/model-core';
import {
  findChildFormDetails,
  IFormDetailController,
} from '@ibiz-template/runtime';
import FormMDCtrlContainer from '../../form-mdctrl-container/form-mdctrl-container';
import { FormController } from '../../../../form';
import { FormMDCtrlRepeaterFormOneController } from './form-mdctrl-repeater-form-one.controller';

export const FormMDCtrlRepeaterFormOne = defineComponent({
  name: 'IBizFormMDCtrlRepeaterFormOne',
  props: {
    controller: {
      type: Object as PropType<FormMDCtrlRepeaterFormOneController>,
      required: true,
    },
  },
  setup(props, { slots }) {
    const ns = useNamespace('form-mdctrl');

    useController(props.controller);

    const c: FormMDCtrlRepeaterFormOneController = props.controller;

    c.state = reactive(c.state);

    c.useFormMdCtrlCtx();
    /** 作用域插槽提供的参数 */
    const slotProps: IData = { form: c };
    const getDetailController = (
      itemController: Array<{ name: string; c: IFormDetailController }>,
      name: string,
    ): IFormDetailController | undefined => {
      const detail = itemController.find(item => {
        return item.name === name;
      });
      return detail?.c;
    };

    /**
     * 按照类型绘制表单成员
     * @author lxm
     * @date 2023-06-12 06:24:14
     * @param {IDEFormDetail} detail
     * @return {*}  {(VNode | VNode[] | undefined)}
     */
    const renderByDetailType = (
      detail: IDEFormDetail,
      item: IData,
    ): VNode | VNode[] | undefined => {
      if ((detail as IDEFormItem).hidden) {
        return;
      }
      const detailId = detail.id!;

      const controller = getDetailController(c.formDetail, detailId);

      // 表单成员组件的props
      const detailProps: IData = {
        modelData: detail,
        controller,
        key: detail.id,
      };
      // 有插槽走插槽
      if (slots[detailId]) {
        return renderSlot(slots, detailId, {
          ...slotProps,
          ...detailProps,
        });
      }

      // 子插槽
      const childSlots: IData = {};
      // 表单项如果有编辑器插槽的时候，调用插槽绘制表单项的默认插槽。
      if (detail.detailType === 'FORMITEM' && slots[`${detailId}_editor`]) {
        childSlots.default = (...args: IData[]): VNode[] => {
          return slots[`${detailId}_editor`]!(...args);
        };
      }
      const childDetails = findChildFormDetails(detail);
      if (childDetails.length) {
        // 容器成员绘制子成员
        childSlots.default = (): (VNode | VNode[] | undefined)[] =>
          childDetails.map(child => {
            return renderByDetailType(child, item);
          });
      }

      // 根据适配器绘制表单成员
      const provider = (controller?.form as FormController).providers[detailId];
      if (!provider) {
        return (
          <div>暂未支持的表单项类型: {detail.detailType}或找不到对应适配器</div>
        );
      }
      const component = resolveComponent(provider.component) as string;
      return (
        <iBizCol
          layoutPos={detailProps.modelData.layoutPos}
          state={detailProps.controller.state}
        >
          {h(
            component,
            {
              ...detailProps,
            },
            childSlots,
          )}
        </iBizCol>
      );
    };
    return { ns, c, renderByDetailType };
  },
  render() {
    if (!this.c || !this.c.state.isInit) {
      return;
    }
    const renderDetails = (
      item: IData,
    ): (VNode | VNode[] | undefined)[] | null | undefined => {
      if (!this.c.data) {
        return null;
      }
      return this.c.model.deformDetails?.map(detail => {
        return this.renderByDetailType(detail, item);
      });
    };
    const renderContent = (): VNode => {
      return (
        <div class={this.ns.b('form-content')}>
          <div class={this.ns.b('form-content-container')}>
            <iBizRow layout={this.c.model.layout}>
              {renderDetails(this.c.data)}
            </iBizRow>
          </div>
        </div>
      );
    };

    return (
      <FormMDCtrlContainer controller={this.c.parent} buttonVisible={false}>
        {renderContent()}
      </FormMDCtrlContainer>
    );
  },
});

export default FormMDCtrlRepeaterFormOne;
